using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Workflow;
using System.Xml;
using Microsoft.SharePoint;
using System.IO;
using System.Diagnostics;
using Microsoft.SharePoint.Utilities;
using DP.Sharepoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

namespace DP.Sharepoint.Workflow
{



    [Serializable]
    //Provides support to Workflow by providing access methods to the form to which the workflow is attached
    public class IPAccessHelper:IDisposable
    {
        public static readonly string IPDateTimeFormatString = "yyyy-MM-ddTHH:mm:ss";

        public SPWorkflowActivationProperties WorkflowProperties;

        public XmlDocument FormData;

        private string _namespaceValue;

        public string NamespaceValue
        {
            get { return _namespaceValue; }
          
        }

        public SPWeb Web
        {
            get { return this.FormFile.Item.Web; }
        }

        public SPListItem ListItem
        {
            get { return this.FormFile.Item; }
        }

        [NonSerialized]
        private XmlNamespaceManager _namespaceManager;

        [NonSerialized]
        private SPFile _formFile;

        public SPFile FormFile
        {
            get
            {
                if (_formFile == null)
                {
                    SPSite site = new SPSite(WorkflowProperties.SiteId);

                    SPWeb web = site.AllWebs[WorkflowProperties.WebId];

                    _formFile = web.GetFile(WorkflowProperties.ItemUrl);
                }

                return _formFile;
            }
        }

        public XmlNamespaceManager NamespaceManager
        {
            get { return GetNamespaceManager(); }
        }

        private XmlNamespaceManager GetNamespaceManager()
        {
            if (_namespaceManager == null)
            {
                _namespaceManager = new XmlNamespaceManager(FormData.NameTable);

                _namespaceManager.AddNamespace("my", this.NamespaceValue);
            }

            return _namespaceManager;

        }

        /// <summary>
        /// work
        /// </summary>
        /// <param name="workflowProperties"></param>
        /// <param name="namespace_my_value"></param>
        public IPAccessHelper(SPWorkflowActivationProperties workflowProperties)
        {
            this.WorkflowProperties = workflowProperties;
         
        }

        public IPAccessHelper(WorkflowContext ctx)
        {
            this.WorkflowProperties = GetActivationPropertyObjFromWokflowContext(ctx);

        }

        /// <summary>
        /// loads form from document library
        /// </summary>
        /// <returns></returns>
        public bool LoadForm()
        {
            // Load the document from the library
            FormData = new XmlDocument();

                using (Stream s = FormFile.OpenBinaryStream())
                {
                    FormData.Load(s);
                }
     
            this._namespaceValue = FormData.DocumentElement.NamespaceURI;


            return true;

        }

        /// <summary>
        /// persists the form to document library
        /// </summary>
        /// <returns></returns>
        public bool SaveForm()
        {
            // Create a MemoryStream to save the document
            MemoryStream ms = new MemoryStream();

            XmlWriterSettings settings = new XmlWriterSettings();

            settings.Encoding = Encoding.UTF8;

            settings.Indent = true;

            settings.NewLineHandling = NewLineHandling.Entitize;

            XmlWriter myTopWriter = XmlWriter.Create(ms, settings);

            FormData.Save(myTopWriter);

            ms.Position = 0;

            this._formFile = null;

            // Save the document
            FormFile.CheckOut();

            FormFile.SaveBinary(ms);

            FormFile.CheckIn(string.Empty);

            this._formFile = null; //clear file cache

            return true;

        }

        /// <summary>
        /// sets value of the current document
        /// </summary>
        /// <param name="property">e.g. //my:ProjectManager</param>
        /// <returns></returns>
        public string GetFormValueInnerText(string property)
        {
            XmlNode node = FormData.SelectSingleNode(property, NamespaceManager);

            return node.InnerText;
        }

        public string GetFormValueInnerXml(string property)
        {
            XmlNode node = FormData.SelectSingleNode(property, NamespaceManager);

            return node.InnerXml;

        }

        public void SetFormValueInnerXml(string property, string value)
        {
            XmlNode node = FormData.SelectSingleNode(property, NamespaceManager);

            node.InnerXml = value;


        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="property"></param>
        public void SetFormValueInnerText(string property, string value)
        {
            XmlNode node = FormData.SelectSingleNode(property, NamespaceManager);


            node.CreateNavigator().SetValue(value);

            //node.InnerText = value;

        }

        /// <summary>
        /// gets activation properties object form workflow context object using reflection
        /// </summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        public static SPWorkflowActivationProperties GetActivationPropertyObjFromWokflowContext(WorkflowContext ctx)
        {
            Type ctxType = ctx.GetType();

            System.Reflection.FieldInfo fiAP = ctxType.GetField("m_inProps", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            return (SPWorkflowActivationProperties)fiAP.GetValue(ctx);
        }

        #region IDisposable Members

        public void Dispose()
        {
            //any cleanup stuff here

            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
